#include <gtest/gtest.h>
#include <iostream>
#include "../../server/mq_host.hpp"

class HostTest : public ::testing::Test 
{
public:
    using empty_map = std::unordered_map<std::string, std::string>;
    virtual void SetUp() override
    {
        p_host = std::make_shared<xzt::VirtualHost>("testhost", "./data/testhost/message/", "./data/testhost/testhost.db");
    
        p_host->declareExchange("exchange1", xzt::ExchangeType::DIRECT, true, false, empty_map());
        p_host->declareExchange("exchange2", xzt::ExchangeType::DIRECT, true, false, empty_map());

        p_host->declareMsgQueue("queue1", false, true, false, empty_map());
        p_host->declareMsgQueue("queue2", false, true, false, empty_map());

        p_host->bind("exchange1", "queue1", ".#..@qwer..");
        p_host->bind("exchange1", "queue2", ".#..@qwer..");
        p_host->bind("exchange2", "queue2", ".#..@qwer..");
        p_host->bind("exchange2", "queue1", ".#..@qwer..");

        p_host->basicPublish("queue1", nullptr, "hello world-1");
        p_host->basicPublish("queue1", nullptr, "hello world-2");
        p_host->basicPublish("queue1", nullptr, "hello world-3");

        p_host->basicPublish("queue2", nullptr, "hello world-1");
        p_host->basicPublish("queue2", nullptr, "hello world-2");
        p_host->basicPublish("queue2", nullptr, "hello world-3");

    }

    virtual void TearDown() override
    {
        p_host->clear();
    }

public:
    xzt::VirtualHost::ptr p_host;
};

TEST_F(HostTest, init_test)
{
    // 测试交换机是否存在
    EXPECT_TRUE(p_host->existsExchange("exchange1"));
    EXPECT_TRUE(p_host->existsExchange("exchange2"));

    // 测试队列是否存在
    EXPECT_TRUE(p_host->existsMsgQueue("queue1"));
    EXPECT_TRUE(p_host->existsMsgQueue("queue2"));

    // 测试队列是否绑定到交换机
    EXPECT_TRUE(p_host->existsBinding("exchange1", "queue1"));
    EXPECT_TRUE(p_host->existsBinding("exchange1", "queue2"));
    EXPECT_TRUE(p_host->existsBinding("exchange2", "queue1"));
    EXPECT_TRUE(p_host->existsBinding("exchange2", "queue2"));

    // 测试消费功能 (利用queue1测试)
    auto msg1 = p_host->basicConsume("queue1");
    ASSERT_NE(msg1, nullptr);
    EXPECT_EQ(msg1->payload().body(), std::string("hello world-1"));
    auto msg2 = p_host->basicConsume("queue1");
    ASSERT_NE(msg2, nullptr);
    EXPECT_EQ(msg2->payload().body(), std::string("hello world-2"));
    auto msg3 = p_host->basicConsume("queue1");
    ASSERT_NE(msg3, nullptr);
    ASSERT_NE(msg3, nullptr);
    EXPECT_EQ(msg3->payload().body(), std::string("hello world-3"));
    // 队列1中只有3条消息，第4条消息应该为空
    auto msg4 = p_host->basicConsume("queue1");
    EXPECT_EQ(msg4, nullptr);
}

TEST_F(HostTest, remove_exchange)
{
    // 测试删除交换机
    p_host->deleteExchange("exchange1");
    EXPECT_FALSE(p_host->existsExchange("exchange1"));
    EXPECT_TRUE(p_host->existsExchange("exchange2"));

    // 测试绑定关系是否删除
    EXPECT_FALSE(p_host->existsBinding("exchange1", "queue1"));
    EXPECT_FALSE(p_host->existsBinding("exchange1", "queue2"));
}

TEST_F(HostTest, remove_queue)
{
    // 测试删除队列
    p_host->deleteMsgQueue("queue1");
    EXPECT_FALSE(p_host->existsMsgQueue("queue1"));
    EXPECT_TRUE(p_host->existsMsgQueue("queue2"));

    // 测试绑定关系是否删除
    EXPECT_FALSE(p_host->existsBinding("exchange1", "queue1"));
    EXPECT_TRUE(p_host->existsBinding("exchange1", "queue2"));
    EXPECT_FALSE(p_host->existsBinding("exchange2", "queue1"));
    EXPECT_TRUE(p_host->existsBinding("exchange2", "queue2"));
}

TEST_F(HostTest, ack_test)
{
    // 测试确认消息
    auto msg1 = p_host->basicConsume("queue1");
    ASSERT_NE(msg1, nullptr);
    EXPECT_EQ(msg1->payload().body(), std::string("hello world-1"));
    p_host->basicAck("queue1", msg1->payload().propeties().id());

    auto msg2 = p_host->basicConsume("queue1");
    ASSERT_NE(msg2, nullptr);
    EXPECT_EQ(msg2->payload().body(), std::string("hello world-2"));
    p_host->basicAck("queue1", msg2->payload().propeties().id());

    auto msg3 = p_host->basicConsume("queue1");
    ASSERT_NE(msg3, nullptr);
    ASSERT_NE(msg3, nullptr);
    EXPECT_EQ(msg3->payload().body(), std::string("hello world-3"));
    p_host->basicAck("queue1", msg3->payload().propeties().id());

    // 队列1中只有3条消息，第4条消息应该为空
    auto msg4 = p_host->basicConsume("queue1");
    EXPECT_EQ(msg4, nullptr);

    DLOG("exchange1 is exist: %d", p_host->existsExchange("exchange1"));
    DLOG("msgqueue1 is exist: %d", p_host->existsMsgQueue("queue1"));
}

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}